
/**
 * Implementation of this HashMap based on two arrays: array of values(arrayInteger) ​​and an array of keys(keys). Their initial length is given to the constructor. 
 * Adding (method put(Integer key, Integer value)) as follows: calculate the value index = key.hashCode() % arrayInteger.length, 
 * if arrayInteger[index] is null, then add, otherwise pass through the array and search space (all of this in the method putHelp(Integer key, Integer value)). 
 * In the case where the full array (size == arrayInteger.length) doubling it, overwrite with changing indexes and add element already in the new array. 
 * Accordingly, the method get(Integer key) calculates the index = key.hashCode() % arrayInteger.length, and if the keys do not match, iterates through the array 
 * until the moment when we find an element.
 * @author Troitskaya Anastasia
 *
 */
public class MyHashMap {
	private Integer[] arrayInteger;
	private Integer[] keys;
	private int size;
	public MyHashMap(int startSizeOfArray) {
		this.arrayInteger = new Integer[startSizeOfArray];
		this.keys = new Integer[startSizeOfArray];
		this.size = 0;
	}
	public Integer put(Integer key, Integer value) {
		if (size < arrayInteger.length) {
			putHelp(key, value);
			return value;
		}
		else {
			Integer[] arrayIntegerNew = new Integer[2*arrayInteger.length];
			Integer[] keysNew = new Integer[2*arrayInteger.length];
			for (int i = 0; i < arrayInteger.length; i++) {
				int newIndex = calculationIndex(keys[i],2*arrayInteger.length,0);
				if (arrayIntegerNew[newIndex] == null) {
					arrayIntegerNew[newIndex] = arrayInteger[i];
					keysNew[newIndex] = keys[i];
				}
				else {
					int j = 0;
					while ((arrayIntegerNew[newIndex] != null)&&(j < 2*(arrayInteger.length))) {
						newIndex = calculationIndex(keys[i],arrayIntegerNew.length,j);
						j++;
					}
					arrayIntegerNew[newIndex] = arrayInteger[i];
					keysNew[newIndex] = keys[i];
				}
			}
		arrayInteger = arrayIntegerNew;
		keys = keysNew;
		putHelp(key, value);
		return value;
		}
	}
	public void printHashMap() {
		for (int i = 0; i < arrayInteger.length; i++)
			System.out.println(arrayInteger[i]+" "+"key"+" "+keys[i]);
	}
	public Integer get(Integer key) {
		Integer index = searchIndex(key);
		if (index == null)
			return null;
		else
			return arrayInteger[index];
	}
	private Integer searchIndex(Integer key) {
		int index = calculationIndex(key,arrayInteger.length,0);
		if (keys[index] == key)
			return index;
		else {
			int j = 1;
			while (((int)keys[index] != (int)key)&&(j < arrayInteger.length)) {
				index = calculationIndex(key,arrayInteger.length,j);
				j++;
			}
			if (j == arrayInteger.length) {
				return null;
			}
			else
				return index;
		}
	}
	public void remove(Integer key) {
		Integer index = searchIndex(key);
		if (index != null) {
			arrayInteger[index] = 0;
			keys[index] = 0;
		}
	}
	public void clear() {
		for(int i = 0; i < arrayInteger.length; i++) {
			remove(keys[i]);
		}
	}
	private void putHelp(Integer key, Integer value) {
		Integer index;
		index = calculationIndex(key,arrayInteger.length,0);
		if (arrayInteger[index] == null) {
			arrayInteger[index] = value;
			keys[index] = key;
			size++;
		}
		else {
			if (size < arrayInteger.length) {
				int j = 0;
				while ((arrayInteger[index] != null)&&(j < arrayInteger.length)) {
					index = calculationIndex(key, arrayInteger.length, j);
					j++;
				}
				arrayInteger[index] = value;
				keys[index] = key;
				size++;
			}
		}
	}
	private int calculationIndex(Integer key, int length, int j) {
		return (key.hashCode() + j) % length;
	}
}
